home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Book Chapters
/
03 - Advanced Graphics
/
Example 1
/
demo.c
< prev
next >
Wrap
Text File
|
1995-03-06
|
10KB
|
341 lines
//
// File: demo.c
//
// This file contains the routines that control the demo.
//
// 2/19/95 -- Created by Mick
//
// include files
#include "global.h"
#include <Palettes.h>
#include <QDOffscreen.h>
#include "demo.h"
#include "main.h"
#include "sprite.h"
// defines for this file
#define kMaxObjects 10 // the maximum number of objects in the demo
#define kClipRectInset 100 // the amount to inset the clip rect
// typedefs for this file
typedef struct
{
tSpriteInfo *fSpriteInfo; // the information on the sprite for this object
unsigned char fIsVisible; // should we draw this object
signed long fXPos; // the x position of this object ( 16:16 fixed )
signed long fYPos; // the y position of this object ( 16:16 fixed )
signed long fDeltaX; // the x coord of the velocity of this object
signed long fDeltaY; // the y coord of the velocity of this object
} tObjectInfo;
// global function declarations
void startupDemo( void );
void shutdownDemo( void );
void demoKey( unsigned char inKey );
void doDemoFrame( void );
// global data owned by this file
GWorldPtr gOffscreenBuffer; // the port and gdevice of the offscreen buffer
PixMapHandle gOffscreenPixels; // the actual pixmap of the offscreen buffer
Rect gOffscreenRect; // the size of the offscreen buffer
// local function declarations
static void moveObjects( void ); // move all the objects
static void blitToScreen( void ); // copy data from offscreen to onscreen
static void restoreBackground( void ); // redraw the background
// static data
tObjectInfo sObjects[ kMaxObjects ]; // the data for all the objects
unsigned char sClippingFlag; // are we clipping
Rect sClipRect; // the rect that we are clipping to
// functions
//
// startupDemo -
//
// Create and load all the buffers and data needed for the demo.
//
void startupDemo( void )
{
unsigned short indexCounter; // a counter to scan the object array
// create the offscreen gworld
NewGWorld( &gOffscreenBuffer, 8, &( gMainWindow->portRect ), gAppColorTable, ( GDHandle )kNil, keepLocal );
// get the pixel map and rect
gOffscreenPixels = GetGWorldPixMap( gOffscreenBuffer );
gOffscreenRect = gMainWindow->portRect;
// load the sprite
for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
{
// load the sprites
sObjects[ indexCounter ].fSpriteInfo = loadSprite( kNumberOne + indexCounter );
// give it a random location and velocity
sObjects[ indexCounter ].fXPos = ( Random() & 0x00FF ) << 16;
sObjects[ indexCounter ].fYPos = ( Random() & 0x00FF ) << 16;
sObjects[ indexCounter ].fDeltaX = Random() << 4;
sObjects[ indexCounter ].fDeltaY = Random() << 4;
// initially, it is visible
sObjects[ indexCounter ].fIsVisible = kTrue;
}
// determine the clip rect
sClipRect = gOffscreenRect;
InsetRect( &sClipRect, kClipRectInset, kClipRectInset );
// set the initial flags
sClippingFlag = kFalse;
}
//
// shutdownDemo -
//
// Release all the memory used by the demo.
//
void shutdownDemo( void )
{
unsigned short indexCounter; // a counter to scan the object array
// dump the sprites
for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
{
disposeSprite( sObjects[ indexCounter ].fSpriteInfo );
}
// dump the offscreen gworld
DisposeGWorld( gOffscreenBuffer );
}
//
// demoKey -
//
// Handle a key stroke -- allows the user to set options while the demo runs.
//
void demoKey( unsigned char inKey )
{
// depending on the key pressed
switch( inKey )
{
case 'c': // turn clipping on and off
sClippingFlag = !sClippingFlag;
break;
case '1': // turn this number on and off
sObjects[ 0 ].fIsVisible = !sObjects[ 0 ].fIsVisible;
break;
case '2': // turn this number on and off
sObjects[ 1 ].fIsVisible = !sObjects[ 1 ].fIsVisible;
break;
case '3': // turn this number on and off
sObjects[ 2 ].fIsVisible = !sObjects[ 2 ].fIsVisible;
break;
case '4': // turn this number on and off
sObjects[ 3 ].fIsVisible = !sObjects[ 3 ].fIsVisible;
break;
case '5': // turn this number on and off
sObjects[ 4 ].fIsVisible = !sObjects[ 4 ].fIsVisible;
break;
case '6': // turn this number on and off
sObjects[ 5 ].fIsVisible = !sObjects[ 5 ].fIsVisible;
break;
case '7': // turn this number on and off
sObjects[ 6 ].fIsVisible = !sObjects[ 6 ].fIsVisible;
break;
case '8': // turn this number on and off
sObjects[ 7 ].fIsVisible = !sObjects[ 7 ].fIsVisible;
break;
case '9': // turn this number on and off
sObjects[ 8 ].fIsVisible = !sObjects[ 8 ].fIsVisible;
break;
case '0': // turn this number on and off
sObjects[ 9 ].fIsVisible = !sObjects[ 9 ].fIsVisible;
break;
default: // unknown key
SysBeep( 0 );
break;
}
}
//
// doDemoFrame -
//
// Move the demo ahead one frame -- move the sprites and draw.
//
void doDemoFrame( void )
{
CGrafPtr oldPort; // the graf port that is in place when we are called
GDHandle oldDevice; // the gdevice that is in place when we are called
signed short indexCounter; // a counter to scan all the objects
Rect clipFrame; // the rect of the frame to the clipping area
Point drawPoint; // where to draw the sprite
// save the current port and gdevice
GetGWorld( &oldPort, &oldDevice );
// set the offscreen buffer as current ( and lock the pixel map )
SetGWorld( gOffscreenBuffer, ( GDHandle )kNil );
LockPixels( gOffscreenPixels );
// restore the background
restoreBackground();
// move the objects
moveObjects();
// setup to draw the shapes (and handle the clipping)
if ( sClippingFlag )
{
clipFrame = sClipRect;
InsetRect( &clipFrame, -1, -1 );
FrameRect( &clipFrame );
startSpriteDraw( &sClipRect );
}
else
{
startSpriteDraw( &gOffscreenRect );
}
// draw the sprites from back to front
for( indexCounter = kMaxObjects - 1; indexCounter >= 0; indexCounter-- )
{
if ( sObjects[ indexCounter ].fIsVisible )
{
drawPoint.h = ( sObjects[ indexCounter ].fXPos ) >> 16;
drawPoint.v = ( sObjects[ indexCounter ].fYPos ) >> 16;
drawSprite( sObjects[ indexCounter ].fSpriteInfo, drawPoint );
}
}
// shutdown the shape draw
endSpriteDraw();
// copy the buffer to the screen
blitToScreen();
// restore the current port and gdevice
UnlockPixels( gOffscreenPixels );
SetGWorld( oldPort, oldDevice );
}
//
// moveObjects -
//
// Move all the objects.
//
void moveObjects( void )
{
unsigned short indexCounter; // a counter to scan all the objects
// concider each object
for( indexCounter = 0; indexCounter < kMaxObjects; indexCounter++ )
{
// apply the velocity
sObjects[ indexCounter ].fXPos += sObjects[ indexCounter ].fDeltaX;
sObjects[ indexCounter ].fYPos += sObjects[ indexCounter ].fDeltaY;
// if the object has hit an edge, bounce it
if( sObjects[ indexCounter ].fXPos < ( gOffscreenRect.left << 16 ) )
{
sObjects[ indexCounter ].fDeltaX *= -1;
sObjects[ indexCounter ].fXPos += ( gOffscreenRect.left << 16 ) - sObjects[ indexCounter ].fXPos;
}
if( sObjects[ indexCounter ].fYPos < ( gOffscreenRect.top << 16 ) )
{
sObjects[ indexCounter ].fDeltaY *= -1;
sObjects[ indexCounter ].fYPos += ( gOffscreenRect.top << 16 ) - sObjects[ indexCounter ].fYPos;
}
if( sObjects[ indexCounter ].fXPos +
( ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.right -
( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.left ) << 16 ) >
( gOffscreenRect.right << 16 ) )
{
sObjects[ indexCounter ].fDeltaX *= -1;
sObjects[ indexCounter ].fXPos += ( ( gOffscreenRect.right -
( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.right -
( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.left ) ) << 16 ) -
sObjects[ indexCounter ].fXPos;
}
if( sObjects[ indexCounter ].fYPos +
( ( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.bottom -
( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.top ) << 16 ) >
( gOffscreenRect.bottom << 16 ) )
{
sObjects[ indexCounter ].fDeltaY *= -1;
sObjects[ indexCounter ].fYPos += ( ( gOffscreenRect.bottom -
( ( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.bottom -
( sObjects[ indexCounter ].fSpriteInfo )->fSpriteRect.top ) ) << 16 ) -
sObjects[ indexCounter ].fYPos;
}
}
}
//
// blitToScreen -
//
// This routine updates the screen from the offscreen buffer.
//
void blitToScreen( void )
{
CGrafPtr oldPort; // the graf port that is in place when we are called
GDHandle oldDevice; // the gdevice that is in place when we are called
// save the current port and gdevice
GetGWorld( &oldPort, &oldDevice );
// set the drawing environment to the screen
SetGWorld( ( CWindowPtr )gMainWindow, GetMainDevice() );
// make sure that the fore and back colors are correct to prevent colorize mode
ForeColor( blackColor );
BackColor( whiteColor );
// Copy the screen's color table seed into the source pixmap.
// This will minimize CopyBits' setup time.
( *( ( *gOffscreenPixels )->pmTable ) )->ctSeed = ( *( ( *( ( *( GetGDevice() ) )->gdPMap ) )->pmTable ) )->ctSeed;
// copy the buffer to the screen
CopyBits( ( BitMap * )( *gOffscreenPixels ), &( gMainWindow->portBits ),
&gOffscreenRect, &( gMainWindow->portRect ),
srcCopy, ( RgnHandle )kNil );
// restore the current port and gdevice
SetGWorld( oldPort, oldDevice );
}
//
// restoreBackground -
//
// This routine redraws the background over changed areas.
//
void restoreBackground( void )
{
// erase the entire offscreen
EraseRect( &gOffscreenRect );
}